home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / zcpp_jae.zip / PAPER.MSS < prev    next >
Text File  |  1990-07-17  |  33KB  |  694 lines

  1. .nr PS 10
  2. .nr VS 12
  3. .nr PD .7v
  4. .nr LL 6.5i
  5. .TL
  6.  
  7. **** EARLY DRAFT ****
  8.  
  9.  
  10. A Portable Implementation of Parameterized Templates Using
  11. A Sophisticated C++ Macro Facility
  12.  
  13.  
  14. **** EARLY DRAFT ****
  15.  
  16. .AU
  17. Mary Fontana
  18. LaMott Oren
  19. .AI
  20. Texas Instruments Incorporated
  21. Computer Science Center
  22. Dallas, TX
  23. .AU
  24. Martin Neath
  25. .AI
  26. Texas Instruments Incorporated
  27. Information Technology Group
  28. Austin, TX
  29. .ND 
  30. .AB
  31. The Texas Instruments C++ Object-Oriented Library (COOL) is a collection of
  32. classes, templates and macros for use by C++ programmers writing complex
  33. applications.  Parameterized types, symbolic computing and exception handling
  34. are significant features of COOL which improve the development capabilities
  35. available to the programmer.  These features are implemented in COOL with a
  36. sophisticated C++ macro facility.  This paper describes the COOL macro
  37. facility, discusses how support for parameterized templates is built upon it,
  38. and provides details of two programmer interfaces (both implemented) for easy
  39. use of parameterized templates in application programs.
  40. .AE
  41. .NH 1
  42. Introduction
  43. .LP
  44. The Texas Instruments C++ Object-Oriented Library (COOL) is a collection of
  45. classes, templates and macros for use by C++ programmers writing complex
  46. applications. It is designed to raise the level of abstraction for the
  47. programmer in order to facilitate concentration on the problem domain, not on
  48. implementing base data structures, macros, and classes.  In addition, COOL
  49. provides a system-independent software platform on top of which applications
  50. are built. Parameterized templates, symbolic computing, and exception handling
  51. are significant features of COOL which substantially improve the development
  52. capabilities available to the C++ programmer.  We wished to provide these
  53. facilities in a compiler- and machine-independent manner across several
  54. hardware platforms.  We examined the macro definition and expansion mechanism
  55. found in standard C-preprocessors and determined that it is not sufficient for
  56. implementing these features.  As a result, we developed the COOL macro facility
  57. to allow the programmer to define powerful extensions to the C++ language in a
  58. seamless and unobtrusive manner.  This macro facility is implemented as an
  59. extension to a standard C preprocessor [1].  The modifications made to the
  60. preprocessor are both portable and compiler independent.  This paper describes
  61. this enhanced macro facility, discusses how parameterized templates is built
  62. upon it, and provides details of two programmer interfaces (both implemented)
  63. for easy use of parameterized templates.  For an overview of COOL see the
  64. paper,
  65. .I
  66. COOL - A C++ Object-Oriented Library 
  67. .R
  68. [2].
  69. For complete details, see the reference document,
  70. .I
  71. COOL User's Manual
  72. .R
  73. [3].
  74. .NH 1
  75. The COOL Preprocessor and the defmacro Keyword
  76. .LP
  77. Many C++ language implementations separate the preprocessor and compiler
  78. functions into two separate programs. Others, (such as the Glockenspiel C++
  79. language system), combine the preprocessor and compiler into one step. Since
  80. we needed a portable utility to massage C++ source code that works under both
  81. scenarios and executes after include files and standard preprocessor
  82. directives have been expanded, but before the C++ compiler itself begins
  83. parsing, we decided to modify a C-preprocessor to support the COOL C++ language
  84. extensions. Thus, the COOL preprocessor is derived from and based upon a
  85. public domain C-preprocessor (the DECUS C preprocessor) made available by the
  86. DEC User's group and supplied on the X11R3 source tape from MIT. It has been
  87. modified to comply with the draft ANSI C specification with the exception that
  88. trigraph sequences are not supported.
  89.  
  90. The draft-proposed ANSI C standard indicates that extensions and changes to the
  91. language or features implemented in a preprocessor or compiler should be made
  92. by using the \fB#pragma\fR keyword.  The COOL preprocessor recognizes a
  93. \fB#pragma defmacro\fR declaration and is the single hook through which
  94. features such as the class macro, parameterized templates, and polymorphic
  95. enhancements have been implemented. The \fBdefmacro\fR keyword provides a way
  96. to define and execute arbitrary filter programs or macro expanders on C++ code
  97. fragments.  The syntax of the \fBdefmacro\fR declaration is:
  98. .DS I
  99. \fB#pragma \fBdefmacro \fIname \fB"\fIprogram\fB"\fI options\fR
  100. \fB#pragma \fBdefmacro \fIname \fB<\fIprogram\fB>\fI options\fR
  101. .DE
  102. where \fIname\fR is the name of the macro, \fIprogram\fR is either the name of
  103. an executable file or the name of an internal preprocessor function which
  104. implements the macro expansion, and \fIoptions\fR are any combination of the
  105. following optional parameters:
  106. .DS I
  107. \fBrecursive\fR        - the macro may be recursively expanded.
  108. \fBexpanding\fR        - the input to the macro is expanded.
  109. \fBdelimiter= \fIx\fR    - the default delimiter (semi-colon) is replaced with \fIx\fR.
  110. .DE
  111. Unknown \fIoptions\fR are passed as arguments to the macro expander named
  112. \fIprogram\fR.  This provides the necessary handle through which COOL functions
  113. and language extensions can be identified. For example, the \fBMACRO\fR
  114. and \fBtemplate\fR keywords are defined in a top-level header file with:
  115. .DS I
  116. #pragma defmacro MACRO "macro" delimiter=} recursive
  117. #pragma defmacro template "template" delimiter=}
  118. .DE
  119. The implementation of the macro expander program may be either external or
  120. internal to the preprocessor.  Fundamental COOL macro-expanders are implemented
  121. internal to the COOL preprocessor for the sole reason of providing a more
  122. efficient execution profile to reduce compile time for the application
  123. programmer.  When the preprocessor encounters a \fBdefmacro\fR declaration in
  124. the source code, it searches first for an executable file named \fIprogram\fR
  125. on the same search path as that used for include files.  If a match is not
  126. found, it then searches for \fIprogram\fR in an internal preprocessor function
  127. table.  If a match is still not found, an error is reported indicating that the
  128. macro expander could not be found.  This search order allows an internal
  129. preprocessor definition to be overridden by an external one.
  130.  
  131. When a \fBdefmacro\fR name is successfully recognized, the name and all
  132. following characters upto and including the delimiter character (including all
  133. matching and nested levels of \fB{} [] () <> "" ''\fR and comments found along
  134. the way) are piped into the standard input of the macro expander program.  The
  135. expander program performs whatever function(s) is appropriate and the resulting
  136. massaged character stream is piped back onto the standard output of the macro
  137. expander.  This output stream is scanned as new input by the preprocessor for
  138. any further processing that might be necessary. The original text in the source
  139. file is replaced with the preprocessor output before being sent onto the C++
  140. compiler.  The expansion replacing a \fBdefmacro\fR name in the source code is
  141. C++ 2.0 syntax acceptable to any conforming C++ translator or compiler [4].
  142. .NH 1
  143. The MACRO Keyword
  144. .LP
  145. The COOL \fBMACRO\fR keyword provides a powerful and flexible macro
  146. capability used to implement and simplify many of the features and functions
  147. contained in the library. A \fBdefmacro\fR named \fBMACRO\fR (all uppercase)
  148. provides an enhanced \fB#define\fR macro that supports multi-line, arbitrary
  149. length, nested macros and cpp-directives with positional, optional, optional
  150. keyword, required keyword, rest, and body arguments. \fBMACRO\fR has the
  151. following syntax:
  152. .DS I
  153. \fBMACRO \fIname\fR \fB( \fIparmlist\fR\fB ) { \fIbody\fR \fB}\fR
  154. \fIparmlist\fR  :=  [\fBKEY:\fR | \fBREST:\fR | \fBBODY:\fR] \fIidentifier\fR [\fB=\fR \fIidentifier\fR] [\fB,\fR \fIparmlist\fR]
  155. .DE
  156. where \fIname\fR is the name of the macro, \fIparmlist\fR is a list of
  157. parameters separated by commas, and \fIbody\fR is the code which replaces the
  158. \fBMACRO\fR reference. The \fIparmlist\fR specification allows positional,
  159. keyword, rest, and body parameters to be identified by the programmer.  The
  160. positional and keyword parameters may be required or optional. Optional
  161. parameters are supported by use of an equal sign followed by an
  162. \fIidentifier\fR that specifies the default value.  All the optional
  163. positional parameters must follow all of the required positional ones.  
  164.  
  165. When \fBKEY:\fR is specified in the \fIparmlist\fR, all parameters which follow
  166. are keyword parameters.  Keyword parameters are position-independent
  167. parameters.  A keyword parameter is provided a value in an argument list by
  168. supplying the keyword name followed by an equal sign and the argument value.
  169. \fBREST:\fR in the \fIparmlist\fR indicates that the remaining parameters are
  170. referenced by one named \fIidentifier\fR.  An optional equal sign followed by
  171. an \fIidentifier\fR sets the \fIidentifier\fR after the equal sign to the
  172. number of arguments remaining.  Finally, \fBBODY:\fR in the \fIparmlist\fR
  173. indicates that the parameter which follows is expanded to include all the
  174. source code within the braces after the \fBMACRO\fR call.  This is useful for
  175. passing a source code fragment onto other nested \fBMACRO\fRs. Examples of these
  176. three types of arguments are given below.
  177. .NH 2
  178. MACRO Examples
  179. .LP
  180. The following examples show some of the power and flexibility of \fBMACRO\fR.
  181. This first example uses both positional parameters and keyword parameters.
  182. .DS I
  183. MACRO set_val (size, value=NULL, KEY: low=0, high) {
  184.     init (size, value, low, (high-low))
  185. }
  186. .DE
  187. \fBset_val\fR has three parameters: \fIsize\fR is a required positional
  188. parameter, \fIvalue\fR is an optional positional parameter that if not
  189. specified in a particular call has a default value of \fBNULL\fR, \fIlow\fR is
  190. an optional keyword parameter with a default value of \fB0\fR, and \fIhigh\fR is
  191. a required keyword parameter.  In this example, the expansion calls the
  192. function \fBinit\fR with four arguments. The following shows several expansions
  193. of \fBset_val\fR.
  194. .DS I
  195. set_val (0, high=20)        ---->       init (0, NULL, 0, (20-0));
  196. set_val (0, low=5, high=15)    ---->       init (0, NULL, 5, (15-5));
  197. set_val (1, 2, high=25)        ---->       init (1, 2, 0, (25-0));
  198. .DE
  199. The next example uses the \fBREST:\fR parameter.  Note that there are two
  200. \fBMACRO\fRs defined: \fBbuild_table\fR calls \fBbuild_table_internal\fR
  201. to do most of the work.
  202. .DS I
  203. MACRO build_table (name, REST: rest) {
  204.     char* name[] = { build_table_internal(rest) NULL}
  205. }
  206.  
  207. MACRO build_table_internal (first, REST: rest=count) {
  208.     #first,
  209.     #if count
  210.     build_table_internal (rest)
  211.     #endif
  212. }
  213. .DE
  214. \fBbuild_table\fR has two parameters: \fIname\fR is the name of the table of
  215. \fBchar*\fR's and \fIrest\fR refers to all the remaining arguments.
  216. \fBbuild_table\fR calls \fBbuild_table_internal\fR passing its \fIrest\fR
  217. argument.  Note that this call is embedded within the initialization braces of
  218. the table and is followed by a \fBNULL\fR. In \fBbuild_table_internal\fR,
  219. \fIfirst\fR is set to the first argument of the \fIrest\fR argument list in the
  220. invoking macro call, and the remaining \fIcount\fR arguments are left in
  221. \fIrest\fR. \fBbuild_table_internal\fR uses the ANSI \fB#\fR character on
  222. \fIfirst\fR to double quote the value. A conditional clause tests \fIcount\fR
  223. to see if there are remaining arguments.  If \fIcount\fR is non-zero, the macro
  224. is called recursively with the remaining arguments.  When there are no more
  225. arguments, \fBbuild_table\fR regains control and appends the \fBNULL\fR
  226. character and closing brace to the result of \fBbuild_table_internal\fR.
  227.  
  228. A sample use of \fBbuild_table\fR is shown below to illustrate the construction
  229. of a \fBNULL\fR-terminated table containing character strings.  The first line
  230. shows the macro call and the second shows the resulting expansion.
  231. .DS I
  232. build_table (table, 1,2,3,4,5,6,7); 
  233. .DE
  234. expands to: 
  235. .DS I
  236. char* table[] = {"1", "2", "3", "4", "5", "6", "7", NULL};
  237. .DE
  238. This last example uses the \fBBODY:\fR parameter and also takes advantage of
  239. the current position feature found in the COOL container classes [2]. This is
  240. used to implement a general purpose loop macro similar to that found in Common
  241. LISP [5].
  242. .DS I
  243. MACRO LOOP (type, identifier, object, BODY: body) {
  244.     { type identifier;
  245.       for ( object.reset(); object.next(); ) {
  246.         identifier = object.value();
  247.         body
  248.       }
  249.     }
  250. }
  251. .DE
  252. \fBLOOP\fR has four parameters: \fItype\fR is the type of each element in a
  253. container class (such as, \fBint\fR), \fIidentifier\fR is the name of a
  254. variable to be declared of the given type, \fIobject\fR is the name of a
  255. container class instance, and \fIbody\fR is the body of code to apply on each
  256. element in the container object.  A specific example for the parameterized
  257. \fBList<int>\fR class is shown below.
  258. .DS I
  259. extern List<int> list1;
  260. LOOP (int, var1, list1) { cout << var1; }
  261. .DE
  262. expands to:
  263. .DS I
  264. extern List<int> list1;
  265. { int var1;
  266.   for ( list1.reset(); list1.next(); )  {
  267.     var1 = list1.value();
  268.     cout << var1;
  269.   }
  270. }
  271. .DE
  272. In this example, \fBlist1\fR is an instance of \fBList<int>\fR which is a
  273. container class representing a list of integers.  \fBLOOP\fR takes this list
  274. object and iterates through the elements, assigning each to a temporary integer
  275. variable \fBvar1\fR and printing its value.  The net result will print all
  276. elements in the list.
  277. .NH 1
  278. COOL Parameterized Templates
  279. .LP
  280. One of the main uses of the COOL macro facility is the implementation
  281. of \fBtemplate\fR, \fBDECLARE\fR and \fBIMPLEMENT\fR for supporting
  282. parameterized templates.  The syntax of the \fBtemplate\fR grammar is that as
  283. specified by Stroustrup in his paper,
  284. .I
  285. Parameterized Types for C++ 
  286. .R
  287. [6].  
  288. COOL fully implements this functionality such that there will be minimal source
  289. code conversion necessary when this feature is finally implemented in the C++
  290. language.  COOL provides templates for a number of parameterized classes (such
  291. as, \fBRange\fR and \fBIterator\fR) and container classes (such as,
  292. \fBVector\fR, \fB List\fR, \fBBinary_Tree\fR and \fBHash_Table\fR) which are
  293. described in
  294. .I
  295. COOL User's Guide 
  296. .R
  297. [3].
  298. .NH 2
  299. The template Keyword
  300. .LP
  301. The \fBtemplate\fR keyword provides a mechanism for defining parameterized
  302. classes.  A parameterized class is a type-independent class.  A typical use is
  303. a container class where the type of the contained object is specified at
  304. compile-time.  For example, vectors can be declared to hold a specific type
  305. of element, such as, a vector of integers or a vector of doubles,
  306. from a single parameterized class, \fBVector<\fItype\fB>\fR.
  307.  
  308. A \fBtemplate\fR is divided into the declarative part and the implementation
  309. part of a class.  The declarative part may occur many times in an application
  310. and is analogous to including a header file for a class which contains the
  311. class definition and its inline member functions.  The implementation part is
  312. analogous to the file that contains the source code implementing the member and
  313. friend functions of the class.  COOL provides four variations of \fBtemplate\fR
  314. for these two parts.
  315.  
  316. .DS I
  317. \fBtemplate\fR <\fBclass\fR \fItype\fR [, \fIparms\fR]> \fBclass\fR \fIname\fR<\fItype\fR> { \fIclass_description\fR };
  318. .RS
  319. Defines the class template for the declarative part of the \fIname\fR class.
  320. .RE
  321.  
  322. \fBtemplate\fR <\fBclass\fR \fItype\fR [, \fIparms\fR]> \fBinline\fR \fIresult name\fR<\fItype\fR>::\fIfunction\fR { ... };
  323. .RS
  324. Defines an inline member function for the declarative part of the \fIname\fR 
  325. class.
  326. .RE
  327.  
  328. \fBtemplate\fR <\fBclass\fR \fItype\fR [, \fIparms\fR]> \fIresult\fR \fIname\fR<\fItype\fR>::\fIfunction\fR { ... };
  329. .RS
  330. Defines a member function for the implementation part of the \fIname\fR class.
  331. .RE
  332.  
  333. \fBtemplate\fR <\fBclass\fR \fItype\fR [, \fIparms\fR]> \fIname\fR { \fIanything\fR };
  334. .RS
  335. Defines anything else associated with a template for the \fIname\fR class.
  336. .RE
  337. .DE
  338. This form is used to define such things as \fBtypedef\fRs or friend functions
  339. of a parameterized class.  When this form is found before the class template,
  340. the contents are expanded before the class definition.  When this form is found
  341. after the class template, the contents are expanded as part of the class
  342. implementation.  Note that this form is not part of the parameterized type
  343. syntax described by Stroustrup [6].  Rather, it is something we found lacking
  344. in the original proposal and found very useful in several COOL container
  345. classes for defining predicate types for the class. Another use of this form is
  346. to provide automatic declarations of nested parameterized classes, that is, to
  347. declare a parameterized class for a class template which is itself derived from
  348. another parameterized class template.
  349.  
  350. Each variation of \fBtemplate\fR allows additional optional parameters
  351. with the following syntax:
  352. .DS I
  353. \fIparms\fR ::= \fItype name\fR [\fB=\fR \fIvalue\fR] [\fB,\fR \fIparms\fR]
  354. .DE
  355. where \fItype\fR is the type of the parameter, (such as, \fBclass\fR or
  356. \fBint\fR); \fIname\fR is the name of the parameter that is substituted when
  357. \fBtemplate\fR is expanded; and \fIvalue\fR is the default value of parameter
  358. \fIname\fR.
  359.  
  360. The following is an example of \fBtemplate\fR for the class,
  361. \fBVector<\fItype\fB>\fB.
  362. .DS I
  363. template <class Type> Vector {            // predicate functions
  364.     typedef int (*Vector_Type##_Predicate) (const Type&, const Type&);
  365.     typedef Boolean (*Vector_Type##_Compare) (const Type&, const Type&);
  366. };
  367. .DE
  368. .DS I
  369. template <class Type> class Vector<Type> {    // Parameterized Vector class
  370.   private:
  371.     Type* v;                        // Vector of pointer to Type
  372.     int num_elements;                    // Element count
  373.     int size;                            // Size of vector object
  374.   public:
  375.     Vector<Type> ();                    // Empty constructor
  376.     Vector<Type> (int);                    // Constructor with size
  377.     Vector<Type> (const Vector<Type>&);    // Constructor with reference
  378.     ~Vector<Type> ();                    // Destructor
  379.     inline Type& operator[](int n);            // Operator[] overload for Type
  380. .DE
  381. .DS I
  382.     ...                                // ... other member functions ...
  383. };
  384. .DE
  385. .DS I
  386. template <class Type>                    // Overload operator []
  387. inline Type& Vector<Type>::operator[] (int n) {
  388.     return this->v[n];
  389. }
  390. .DE
  391. .DS I
  392. template <class Type>                    // Constructor with size
  393. Vector<Type>::Vector<Type> (int n) {
  394.     this->v = new Type[n];
  395.     this->size = n;
  396.     this->num_elements = 0;
  397. }
  398.  
  399.  ...                                // ... other member functions ...
  400. .DE
  401. .NH 2
  402. An Initial Programmer Interface: DECLARE and IMPLEMENT
  403. .LP
  404. As stated earlier, a \fBtemplate\fR for a parameterized class is divided into a
  405. declarative part and an implementation part.  In our first attempt at
  406. implementing parameterized template support, the programmer creates instances
  407. of a parameterized class using \fBDECLARE\fR to expand the declarative part and
  408. \fBIMPLEMENT\fR to expand the implementation part.  \fBDECLARE\fR defines the
  409. parameterized class for a specific type and \fBIMPLEMENT\fR generates the
  410. member functions supporting this type-specific class.  \fBDECLARE\fR must be
  411. used in every file that includes or makes use of the parameterized class.
  412. \fBIMPLEMENT\fR must be used only once in the application for each type over
  413. which the class is parameterized; otherwise the linker will generate errors
  414. about multiple versions of the same member functions.  For example, to create a
  415. vector of doubles, the following would be used:
  416. .DS I
  417. #include <Vector.h>
  418. DECLARE Vector<double>;
  419. IMPLEMENT Vector<double>;
  420. Vector<double> vs(30);        
  421. .DE
  422. \fBDECLARE\fR expands to code which defines a vector class of doubles and its
  423. associated inline member functions.  \fBIMPLEMENT\fR causes a class definition
  424. with its associated member functions to be generated and expanded in the file.
  425. When compiled, this causes the class \fBVector_double\fR to be declared and
  426. defined. One drawback of the use of \fBIMPLEMENT\fR, however, is the fact that
  427. the \fIentire\fR class with all its member functions is generated and linked
  428. into the program image, even if the programmer only requires the use of two or
  429. three member functions. This problem can be avoided by the use of the COOL C++
  430. Control Program (\fBCCC\fR) discussed below. Continuing with the example above,
  431. the \fBtemplate\fR for the \fBVector<\fItype\fB>\fR class for doubles would
  432. expand to the following code:
  433. .DS I
  434.                                 // predicate functions
  435. typedef int (*Vector_double_Predicate) (const double&, const double&);
  436. typedef Boolean (*Vector_double_Compare) (const double&, const double&);
  437. .DE
  438. .DS I
  439. class Vector_double {                    // Parameterized Vector class
  440. private:
  441.     double* v;                        // Vector of pointer to double
  442.     int num_elements;                    // Element count
  443.     int size;                            // Size of vector object
  444. public:
  445.     Vector_double ();                    // Empty constructor
  446.     Vector_double (int);                    // Constructor with size
  447.     Vector_double (const Vector_double&);    // Constructor with reference
  448.     ~Vector_double ();                    // Destructor
  449.     inline double& operator[](int n);            // Operator[] overload for double
  450. .DE
  451. .DS I
  452.     ...                                // ... other member functions ...
  453. };
  454. .DE
  455. .DS I
  456.                                 // Overload operator []
  457. inline double& Vector_double::operator[] (int n) {
  458.     return this->v[n];
  459. }
  460. .DE
  461. .DS I
  462.                                 // Constructor with size
  463. Vector_double::Vector_double (int n) {
  464.     this->v = new double[n];
  465.     this->size = n;
  466.     this->num_elements = 0;
  467. }
  468.  
  469.  ...                                // ... other member functions ...
  470.  
  471. Vector_double vs(30);        
  472. .DE
  473. Declarations of nested parameterized types and the use of non-type arguments in
  474. a template definition are also supported. For example, it is possible to
  475. declare a vector of vectors of ints with \fBVector<Vector<int>>\fR.  In
  476. addition, a class template derived from another class template is supported,
  477. that is, a type parameter in one template class can be used to declare another
  478. class template of that type.  For example, the COOL 
  479. \fBAssociation<\fIT1\fR,\fIT2\fB>\fR class is
  480. a parameterized container class that takes two type arguments, \fIT1\fR and
  481. \fIT2\fR.  The header file for this class has the following templates.
  482. .DS I
  483. template <class T1, T2> Association {
  484.     DECLARE Pair<T1, T2>;                // Declare Pair object type
  485.     DECLARE Vector<Pair<T1, T2>>;        // Declare Vector of Pairs
  486. }
  487.  
  488.  ...                                // ...
  489. // Association<T1,T2> class definition here
  490.  
  491. .DE
  492. .DS I
  493. template <class T1, T2> Association {
  494.     IMPLEMENT Pair<T1, T2>;
  495.     IMPLEMENT Vector<Pair<T1, T2>>;
  496. }
  497. .DE
  498. By using \fBtemplate\fR in this manner, \fBDECLARE\fR for the
  499. \fBAssociation<\fIT1\fR,\fIT2\fB>\fR class invokes \fBDECLARE\fR on the correct
  500. types for the \fBPair<\fIT1\fR,\fIT2\fB>\fR and \fBVector<\fIType\fB>\fR
  501. classes.  Likewise, \fBIMPLEMENT\fR for the
  502. \fBAssociation<\fIT1\fR,\fIT2\fB>\fR class invokes \fBIMPLEMENT\fR for the
  503. \fBPair<\fIT1\fR,\fIT2\fB>\fR and \fBVector<\fIType\fB>\fR classes.
  504.  
  505. Non-type arguments as template parameters are used to provide guidelines to be
  506. used when a template is expanded. For example, the
  507. \fBN_Tree<\fINode\fR,\fIType\fR,\fInchild\fB>\fR class in COOL takes as
  508. arguments a node type (either static or dynamic), a type specifying the
  509. value-type each node will hold, and an argument that specifies the number of
  510. initial subtrees (or children) each node is to have.  The node argument is
  511. itself the name of a parameterized class and a nested parameterized template
  512. definition is automatically generated based upon the supplied type and number
  513. arguments. As such, a single template can be used to generate several different
  514. classes with different behaviors and features.
  515. .NH 2
  516. A Revised Programmer Interface: COOL C++ Control Program (CCC)
  517. .LP
  518. The \fBDECLARE\fR and \fBIMPLEMENT\fR macros discussed above were the first
  519. programmer interface implemented for parameterized template support.  We soon
  520. discovered, however, that this macro expansion mechanism had two serious
  521. problems. First, the type over which a class was parameterized would have to
  522. support all operators used in the template, even if not applicable or needed.
  523. For example, the COOL \fBList<\fIType\fB>\fR class has several member functions
  524. that use \fBoperator<\fR. However, if what the programmer needs is a list of
  525. window objects and does not ever use \fBList<\fIType\fB>\fR member functions
  526. that require \fBoperator<\fR, compile-time errors from the offending functions
  527. that got macro-expanded are nevertheless generated. Second, With the simplistic
  528. linkers available on many operating systems today, an application gets all of
  529. these member functions linked into the executable image.  Typically, an
  530. application uses only a small percentage of the member functions of a 
  531. parameterized class.  The
  532. remaining unused member functions are useless overhead, increasing program size
  533. and memory requirements.
  534.  
  535. A revised programmer interface for parameterized templates was implemented to
  536. resolve these problems and centers around a new program to be used as the main
  537. interface between the user and the preprocessor/compiler in a make file. This
  538. program, the COOL C++ Control program (\fBCCC\fR), augments the standard
  539. \fBCC\fR script.  For most operations, user options and command line arguments
  540. are passed straight through to the underlying CC program.  However, when the
  541. \fB-X\fR option is specified, the \fBCCC\fR program goes to work in the
  542. following manner.  As Stroustrup[6] suggested, \fB-X"Foo<Bar>"\fR is used on
  543. the command line to indicate that the programmer wants to parameterize class
  544. \fBFoo<\fIType\fB>\fR over some type \fBBar\fR.  Additional options for include
  545. file search path and a user-defined library archive are required as described
  546. below.  \fBCCC\fR finds the header file(s) implementing class Foo and type Bar,
  547. then proceeds to define that type for the compiler.  It then \fIfractures\fR
  548. the implementation of this new type along template boundaries, placing each
  549. non-inline member function in a separate source file, compiling it, and putting
  550. the resulting object file in a user-specified library archive.  If a particular
  551. operator is not defined for the type over which the class is parameterized (as
  552. with the example of \fBoperator<\fR above), a compile time error for that one
  553. file is generated.  However, the remaining member functions, one in each
  554. fractured template, are still compiled and added to the user library.
  555.  
  556. For each parameterized class in an application, \fBCCC\fR fractures the
  557. parameterized class definition along template boundaries, causing each
  558. \fBtemplate\fR specifying a member function of the parameterized class to be
  559. compiled into a separate object file.  These separate object files are then
  560. added to an application-specific object library.  Since each member function is
  561. in its own object module in the library, only those member functions actually
  562. used in the application are linked into the final executable image. To use
  563. \fBCCC\fR, the programmer specifies a library name, one or more header files
  564. containing templates, and specific parameterized classes as command line
  565. arguments to \fBCCC\fR.  Other arguments are passed on unchanged to the C++
  566. compiler and system linker.  A single invocation of \fBCCC\fR can either
  567. process a parameterized class type or compile a C++ source file, but not both.
  568. For example,
  569. .DS I
  570. CCC -lapp -c List.h String.h -X "List<String>"
  571. .DE
  572. expands the template for a list of strings.  The resulting object files from
  573. the fractured parameterized \fBList<\fIType\fB>\fR class are stored in
  574. the library, \fBlibapp.a\fR.  The \fB-c\fR option is passed to the compiler to
  575. indicate that it should not continue with the link phase. The library archive
  576. \fBlibapp.a\fR is added to the list of libraries specified in the make file
  577. to be searched during the link step.
  578.  
  579. The net result is a library archive containing object files, each implementing
  580. one member function for the parameterized class and type. This process solves
  581. the two problems identified above with the use of the macros \fBDECLARE\fR and
  582. \fBIMPLEMENT\fR. First, operators not defined for a type cause compile-time
  583. errors on that one file.  Once a parameterized class has been implemented and
  584. provided in a library, compile errors will only occur when a type is selected
  585. that does not have all operators implemented. The user of the class will see
  586. these, and if the member function in question is required, s/he can add that
  587. necessary operator to the type class.  Second, only member functions actually
  588. used in an application are linked into the final executable image.
  589. .NH 2
  590. Future Improvements to CCC
  591. .LP
  592. \fBCCC\fR essentially provides a more sophisticated version of the
  593. \fBIMPLEMENT\fR macro discussed above. However, the programmer is still
  594. required to place the \fBDECLARE\fR macro in the appropriate files.  One
  595. option under consideration to resolve this problem is the use of a command line
  596. switch similar to the +e0/+e1 switchs on the AT&T cfront translator. Under this
  597. scenario, the equivalent of the +e0 option would be used to declare the type for
  598. a parameterized class and generate the inline member functions (as the
  599. \fBDECLARE\fR macro does) but not to generate the remaining member functions.
  600. The programmer would use the equivalent of the +e1 option on one source file to
  601. cause the remaining non-inline member functions to be generated and placed in a
  602. library archive.
  603.  
  604. A second problem with \fBCCC\fR concerns the specification of nested
  605. parameterized classes. A programmer should be able to use
  606. \fB-X"Vector<List<int>>"\fR on the command line to specify creation of nested
  607. parameterized classes.  Currently, \fBCCC\fR does not handle this case
  608. appropriately. A more sophisticated command line parser should be able to
  609. recognize and implement nested types before trying to expand the outer most
  610. parameterized class.
  611. .NH 1
  612. Conclusion
  613. .LP
  614. The COOL macro facility provides a mechanism to implement significant language
  615. features and extensions for C++ that are unavailable with current language
  616. implementations.  The macro facility is implemented in an enhanced preprocessor
  617. that is both efficient and portable, thus allowing for delivery of enhanced
  618. language features on many platforms. This macro extension is at the heart of
  619. the parameterized templates functionality. \fBCCC\fR is used in place of the
  620. normal procedure for controlling the compilation process.  It provides all of
  621. the functionality of the original \fBCC\fR program with additional support for
  622. the COOL preprocessor and parameterized type expansion.  Finally, the
  623. preprocessor provides an ideal mechanism for quickly prototyping and testing
  624. additional language functions and syntax without requiring access to or
  625. modification of a compiler.
  626. .NH 1 
  627. Status of COOL
  628. .LP
  629. Texas Instruments has been using the enhanced macro facility and the
  630. implementation of parameterized templates internally on several projects for
  631. the last year. Many classes and programs have been successfully designed and
  632. implemented, taking full advantage of the power of parameterized templates and
  633. the enhanced macro facility. In particular, we have found that the use of a
  634. class library supplying many basic parameterized container classes
  635. significantly increases the productivity of the programmer, enabling
  636. applications to be prototyped in a shorter time period than might otherwise be
  637. possible.  COOL is currently up and running on a Sun SPARCstation 1 (TM)
  638. running SunOS (TM) 4.x,
  639. .FS
  640. SunOS and SPARCstation 1 are trademarks of Sun Microsystems, Inc.
  641. .FE
  642. a PS/2 (TM) 
  643. .FS
  644. PS/2 is a trademark of International Business Machines Corporation.
  645. .FE
  646. model 70 running SCO XENIX\(rg
  647. .FS
  648. XENIX is a registered trademark of Microsoft Corporation.
  649. .FE
  650. 2.3, a PS/2 model 70 running OS/2 1.1, and
  651. a MIPS running RISC/os 4.0. The SPARC and MIPS ports utilize the AT&T C++
  652. translator (cfront) version 2.0 and the XENIX and OS/2 ports utilize the
  653. Glockenspiel translator with the Microsoft C compiler.
  654. .NH 1
  655. References
  656. .IP [1]
  657. Brian Kernighan and Dennis Richie,
  658. .I
  659. The C Programming Language,
  660. .R
  661. Second Edition, Printice-Hill, Englewood Cliffs, NJ, 1988.
  662. .IP [2]
  663. Mary Fontana, Martin Neath and Lamott Oren,
  664. .I
  665. COOL - A C++ Object-Oriented Library,
  666. .R
  667. Information Technology Group, Austin, TX, Internal Original Issue January 1990.
  668. .IP [3]
  669. Texas Instruments Incorporated,
  670. .I
  671. C++ Object-Oriented Library User's Manual,
  672. .R
  673. Information Technology Group, Austin, TX, Internal Original Issue January 1990.
  674. .IP [4]
  675. AT&T Incorporated,
  676. .I
  677. C++ Language System Release 2.0,
  678. .R
  679. AT&T Product Reference Manual Select Code 307-146, 1989.
  680. .IP [5]
  681. Guy L. Steele Jr,
  682. .I
  683. Common LISP: The Language,
  684. .R
  685. Second Edition, 1990.
  686. .IP [6]
  687. Bjarne Stroustrup, 
  688. .I
  689. Parameterized Types for C++,
  690. .R
  691. Proceedings of the USENIX C++ Conference, Denver, CO, October 17-21, 1988,
  692. pp. 1-18.
  693.  
  694.